package com.sunshine.pay.service.impl;

import com.sunshine.homepage.dao.ProductsDao;
import com.sunshine.pay.dao.MerchantBalancesDao;
import com.sunshine.pay.dao.OrderDao;
import com.sunshine.pay.dao.OrderItemDao;
import com.sunshine.pay.dao.OrdersCombinedDao;
import com.sunshine.pay.dao.UserBalancesDao;
import com.sunshine.pay.entity.MerchantBalances;
import com.sunshine.pay.entity.Order;
import com.sunshine.pay.entity.OrderItem;
import com.sunshine.pay.entity.OrdersCombined;
import com.sunshine.pay.entity.UserBalances;
import com.sunshine.homepage.entity.Products;

import com.sunshine.pay.service.OrderService;
import lombok.extern.slf4j.Slf4j;
import org.redisson.api.RAtomicLong;
import org.redisson.api.RedissonClient;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sunshine.commcon.util.entity.Result;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * 订单服务实现类
 * 提供订单创建、查询、状态更新等核心功能
 */
@Slf4j
@Service
public class OrderServiceImpl implements OrderService {
    
    @Resource
    private OrderDao orderDao;
    
    @Resource
    private OrderItemDao orderItemDao;
    
    @Resource
    private OrdersCombinedDao ordersCombinedDao;
    
    @Resource
    private ProductsDao productsDao;
    
    @Resource
    private UserBalancesDao userBalancesDao;
    
    @Resource
    private MerchantBalancesDao merchantBalancesDao;
    
    @Resource
    private RedissonClient redissonClient;
    
    /**
     * 创建订单
     * @param userId 用户ID
     * @param orderItems 订单项列表
     * @return 创建的订单信息
     */
    @Override
    @Transactional
    public Result<Order> createOrder(Long userId, List<OrderItem> orderItems) {
        try {
            // 检查库存并预减库存
            for (OrderItem item : orderItems) {
                Products product = productsDao.queryById(item.getProductId());
                if (product == null) {
                    log.warn("商品不存在: 商品ID={}", item.getProductId());
                    throw new RuntimeException("商品不存在: 商品ID=" + item.getProductId());
                }
                
                // 检查商品状态是否为上架状态
                if (product.getStatus() != 1) {
                    log.warn("商品已下架: 商品ID={}", item.getProductId());
                    throw new RuntimeException("商品已下架: 商品ID=" + item.getProductId());
                }
                
                // 使用Redis检查并预减库存
                String stockKey = "product:stock:" + item.getProductId();
                RAtomicLong stock = redissonClient.getAtomicLong(stockKey);
                
                // 如果Redis中没有库存信息，从数据库加载
                if (!stock.isExists()) {
                    stock.set(product.getStock());
                }
                
                // 使用Redis的原子操作扣减库存
                // 先获取当前库存
                long currentStock = stock.get();
                // 检查库存是否充足
                if (currentStock < item.getQuantity()) {
                    log.warn("商品库存不足: 商品ID={}, 需要数量={}, 当前库存={}", 
                             item.getProductId(), item.getQuantity(), currentStock);
                    throw new RuntimeException("商品库存不足: " + product.getProductName());
                }
                // 扣减库存
                long remainingStock = stock.addAndGet(-item.getQuantity());
                
                // 双重检查，确保库存不会为负数
                if (remainingStock < 0) {
                    // 库存不足，回滚已扣减的库存
                    stock.addAndGet(item.getQuantity());
                    log.warn("商品库存不足: 商品ID={}, 需要数量={}, 当前库存={}", 
                             item.getProductId(), item.getQuantity(), currentStock);
                    throw new RuntimeException("商品库存不足: " + product.getProductName());
                }
            }
            
            // 创建订单
            Order order = new Order();
            order.setOrderNo(generateOrderNo()); // 生成订单号
            order.setUserId(userId);
            order.setStatus(1); // 待支付状态
            order.setCreatedAt(new Date());
            
            // 计算总金额
            double totalAmount = 0.0;
            for (OrderItem item : orderItems) {
                totalAmount += item.getPrice() * item.getQuantity();
            }
            order.setTotalAmount(totalAmount);
            
            // 保存订单
            int result = orderDao.insert(order);
            if (result <= 0) {
                // 如果订单创建失败，需要回滚Redis中的库存
                rollbackStock(orderItems);
                log.error("创建订单失败: 用户ID={}", userId);
                return Result.fail("创建订单失败");
            }
            
            // 保存订单项
            for (OrderItem item : orderItems) {
                item.setOrderId(order.getOrderId());
                orderItemDao.insert(item);
                
                // 同时保存到orders_combined表
                OrdersCombined combined = new OrdersCombined();
                combined.setOrderId(order.getOrderId());
                combined.setOrderNo(order.getOrderNo());
                combined.setUserId(order.getUserId());
                combined.setProductId(item.getProductId());
                combined.setProductName(item.getProductName());
                combined.setQuantity(item.getQuantity());
                combined.setPrice(item.getPrice());
                combined.setTotalAmount(order.getTotalAmount());
                combined.setStatus(order.getStatus());
                combined.setPaymentTime(order.getPaymentTime());
                combined.setCreatedAt(order.getCreatedAt());
                ordersCombinedDao.insert(combined);
            }
            
            // 查询完整的订单信息（包含订单项）
            Order fullOrder = getOrderWithItems(order.getOrderId());
            
            log.info("订单创建成功: 订单ID={}, 订单号={}, 用户ID={}", order.getOrderId(), order.getOrderNo(), userId);
            return Result.ok(fullOrder);
        } catch (Exception e) {
            log.error("创建订单时发生异常: 用户ID={}", userId, e);
            return Result.fail("系统异常，创建订单失败: " + e.getMessage());
        }
    }
    
    /**
     * 根据订单ID获取订单详情
     * @param orderId 订单ID
     * @return 订单详情信息
     */
    @Override
    public Result<Order> getOrderById(Long orderId) {
        try {
            Order order = getOrderWithItems(orderId);
            if (order == null) {
                log.warn("订单不存在: 订单ID={}", orderId);
                return Result.fail("订单不存在");
            }
            
            log.info("获取订单详情成功: 订单ID={}", orderId);
            return Result.ok(order);
        } catch (Exception e) {
            log.error("获取订单详情时发生异常: 订单ID={}", orderId, e);
            return Result.fail("系统异常，获取订单详情失败");
        }
    }
    
    /**
     * 根据用户ID获取订单列表
     * @param userId 用户ID
     * @return 用户的订单列表
     */
    @Override
    public Result<List<Order>> getOrdersByUserId(Long userId) {
        try {
            List<Order> orders = orderDao.queryByUserId(userId);
            // 为每个订单加载订单项
            for (Order order : orders) {
                List<OrderItem> orderItems = orderItemDao.queryByOrderId(order.getOrderId());
                order.setOrderItems(orderItems);
            }
            
            log.info("获取用户订单列表成功: 用户ID={}, 订单数量={}", userId, orders.size());
            return Result.ok(orders);
        } catch (Exception e) {
            log.error("获取用户订单列表时发生异常: 用户ID={}", userId, e);
            return Result.fail("系统异常，获取订单列表失败");
        }
    }
    
    /**
     * 更新订单状态
     * @param orderId 订单ID
     * @param status 新的订单状态
     * @return 操作结果
     */
    @Override
    @Transactional
    public Result<Boolean> updateOrderStatus(Long orderId, Integer status) {
        try {
            Order order = orderDao.queryById(orderId);
            if (order == null) {
                log.warn("订单不存在: 订单ID={}", orderId);
                return Result.fail("订单不存在");
            }
            
            order.setStatus(status);
            if (status == 2) { // 已支付状态
                order.setPaymentTime(new Date());
            }
            
            int result = orderDao.update(order);
            if (result > 0) {
                // 同步更新orders_combined表中的订单状态
                OrdersCombined ordersCombined = new OrdersCombined();
                ordersCombined.setOrderId(orderId);
                ordersCombined.setStatus(status);
                if (status == 2) { // 已支付状态
                    ordersCombined.setPaymentTime(new Date());
                }
                ordersCombinedDao.update(ordersCombined);
                
                log.info("订单状态更新成功: 订单ID={}, 新状态={}", orderId, status);
                return Result.ok(true);
            } else {
                log.warn("订单状态更新失败: 订单ID={}, 新状态={}", orderId, status);
                return Result.fail("订单状态更新失败");
            }
        } catch (Exception e) {
            log.error("更新订单状态时发生异常: 订单ID={}, 状态={}", orderId, status, e);
            return Result.fail("系统异常，更新订单状态失败");
        }
    }
    
    /**
     * 用户确认收货
     * @param orderId 订单ID
     * @param userId 用户ID
     * @return 操作结果
     */
    @Override
    @Transactional
    public Result<Boolean> confirmReceipt(Long orderId, Long userId) {
        try {
            Order order = orderDao.queryById(orderId);
            if (order == null) {
                log.warn("订单不存在: 订单ID={}", orderId);
                return Result.fail("订单不存在");
            }
            
            // 检查订单是否属于该用户
            if (!order.getUserId().equals(userId)) {
                log.warn("用户无权限操作该订单: 用户ID={}, 订单ID={}", userId, orderId);
                return Result.fail("无权限操作该订单");
            }
            
            // 检查订单状态是否为已发货
            if (order.getStatus() != 3) {
                if (order.getStatus() == 4) {
                    log.warn("订单已经是完成状态，无法再次确认收货: 订单ID={}, 当前状态={}", orderId, order.getStatus());
                    return Result.fail("订单已经是完成状态，无法再次确认收货");
                } else {
                    log.warn("订单状态不正确，无法确认收货: 订单ID={}, 当前状态={}", orderId, order.getStatus());
                    return Result.fail("订单状态不正确，无法确认收货");
                }
            }
            
            // 更新订单状态为已完成
            order.setStatus(4); // 已完成状态
            int result = orderDao.update(order);
            
            if (result > 0) {
                // 同步更新orders_combined表中的订单状态
                OrdersCombined ordersCombined = new OrdersCombined();
                ordersCombined.setOrderId(orderId);
                ordersCombined.setStatus(4);
                ordersCombinedDao.update(ordersCombined);
                
                // 执行资金转移操作
                Result<Boolean> transferResult = transferFunds(order);
                if (!transferResult.getData()) {
                    log.error("资金转移失败: 订单ID={}", orderId);
                    // 抛出异常以回滚事务
                    throw new RuntimeException("资金转移失败: " + transferResult.getMessage());
                }
                
                // 真正扣减数据库中的库存
                deductDatabaseStock(orderId);
                
                log.info("用户确认收货成功: 订单ID={}, 用户ID={}", orderId, userId);
                return Result.ok(true);
            } else {
                log.warn("用户确认收货失败: 订单ID={}, 用户ID={}", orderId, userId);
                return Result.fail("确认收货失败");
            }
        } catch (Exception e) {
            log.error("用户确认收货时发生异常: 订单ID={}, 用户ID={}", orderId, userId, e);
            throw new RuntimeException("确认收货失败: " + e.getMessage(), e); // 重新抛出异常以确保事务回滚
        }
    }
    
    /**
     * 根据商家ID获取订单列表
     * @param merchantId 商家ID
     * @return 订单列表
     */
    @Override
    public Result<List<Order>> getOrdersByMerchantId(Long merchantId) {
        try {
            // 使用OrdersCombinedDao根据merchantId查询商家订单
            List<OrdersCombined> ordersCombinedList = ordersCombinedDao.queryByMerchantId(merchantId);
            
            // 转换为Order对象列表
            List<Order> orders = new ArrayList<>();
            Map<Long, Order> orderMap = new HashMap<>();
            
            for (OrdersCombined oc : ordersCombinedList) {
                Order order = orderMap.get(oc.getOrderId());
                if (order == null) {
                    order = new Order();
                    order.setOrderId(oc.getOrderId());
                    order.setOrderNo(oc.getOrderNo());
                    order.setUserId(oc.getUserId());
                    order.setTotalAmount(oc.getTotalAmount());
                    order.setStatus(oc.getStatus());
                    order.setPaymentTime(oc.getPaymentTime());
                    order.setCreatedAt(oc.getCreatedAt());
                    order.setOrderItems(new ArrayList<>());
                    orderMap.put(oc.getOrderId(), order);
                    orders.add(order);
                }
                
                // 创建OrderItem并添加到订单中
                OrderItem item = new OrderItem();
                item.setOrderId(oc.getOrderId());
                item.setProductId(oc.getProductId());
                item.setProductName(oc.getProductName());
                item.setQuantity(oc.getQuantity());
                item.setPrice(oc.getPrice());
                order.getOrderItems().add(item);
            }
            
            log.info("获取商家订单列表成功: 商家ID={}, 订单数量={}", merchantId, orders.size());
            return Result.ok(orders);
        } catch (Exception e) {
            log.error("获取商家订单列表时发生异常: 商家ID={}", merchantId, e);
            return Result.fail("系统异常，获取订单列表失败");
        }
    }
    
    /**
     * 商家发货订单
     * @param orderId 订单ID
     * @param merchantId 商家ID
     * @return 操作结果
     */
    @Override
    public Result<Boolean> merchantShipOrder(Long orderId, Long merchantId) {
        try {
            Order order = orderDao.queryById(orderId);
            if (order == null) {
                log.warn("订单不存在: 订单ID={}", orderId);
                return Result.fail("订单不存在");
            }
            
            // 验证商家是否有权限操作该订单（需要关联商品和商家）
            // 查询该商家的所有订单
            List<OrdersCombined> merchantOrders = ordersCombinedDao.queryByMerchantId(merchantId);
            // 检查订单是否属于该商家
            boolean hasPermission = merchantOrders.stream()
                .anyMatch(item -> item.getOrderId().equals(orderId));
            if (!hasPermission) {
                log.warn("商家无权限操作该订单: 商家ID={}, 订单ID={}", merchantId, orderId);
                return Result.fail("无权限操作该订单");
            }
            
            // 检查订单状态是否为已支付
            if (order.getStatus() != 2) {
                log.warn("订单状态不正确，无法发货: 订单ID={}, 当前状态={}", orderId, order.getStatus());
                return Result.fail("订单状态不正确，无法发货");
            }
            
            // 更新订单状态为已发货
            order.setStatus(3); // 已发货状态
            int result = orderDao.update(order);
            
            if (result > 0) {
                // 同步更新orders_combined表中的订单状态
                OrdersCombined ordersCombined = new OrdersCombined();
                ordersCombined.setOrderId(orderId);
                ordersCombined.setStatus(3);
                ordersCombinedDao.update(ordersCombined);
                
                log.info("商家发货成功: 订单ID={}, 商家ID={}", orderId, merchantId);
                return Result.ok(true);
            } else {
                log.warn("商家发货失败: 订单ID={}, 商家ID={}", orderId, merchantId);
                return Result.fail("发货失败");
            }
        } catch (Exception e) {
            log.error("商家发货时发生异常: 订单ID={}, 商家ID={}", orderId, merchantId, e);
            return Result.fail("系统异常，发货失败");
        }
    }
    
    /**
     * 资金转移操作：从用户余额转移到商家余额
     * @param order 订单信息
     * @return 操作结果
     */
    @Transactional
    public Result<Boolean> transferFunds(Order order) {
        try {
            log.info("开始执行资金转移: 订单ID={}, 用户ID={}, 订单金额={}", order.getOrderId(), order.getUserId(), order.getTotalAmount());
            
            // 获取订单项列表
            List<OrderItem> orderItems = orderItemDao.queryByOrderId(order.getOrderId());
            log.info("订单项数量: {}", orderItems.size());
            
            if (orderItems.isEmpty()) {
                log.warn("订单没有任何商品项: 订单ID={}", order.getOrderId());
                return Result.fail("订单没有任何商品项");
            }
            
            // 扣减用户余额
            UserBalances userBalance = userBalancesDao.queryByUserId(order.getUserId());
            if (userBalance == null) {
                log.warn("用户余额账户不存在: 用户ID={}", order.getUserId());
                return Result.fail("用户余额账户不存在");
            }
            
            log.info("用户当前余额: 用户ID={}, 余额={}", order.getUserId(), userBalance.getBalance());
            
            if (userBalance.getBalance() < order.getTotalAmount()) {
                log.warn("用户余额不足: 用户ID={}, 余额={}, 订单金额={}", order.getUserId(), userBalance.getBalance(), order.getTotalAmount());
                return Result.fail("用户余额不足");
            }
            
            userBalance.setBalance(userBalance.getBalance() - order.getTotalAmount());
            userBalance.setUpdatedAt(new Date());
            int userUpdateResult = userBalancesDao.update(userBalance);
            if (userUpdateResult <= 0) {
                log.error("更新用户余额失败: 用户ID={}", order.getUserId());
                return Result.fail("更新用户余额失败");
            }
            log.info("用户余额扣减成功: 用户ID={}, 扣减金额={}", order.getUserId(), order.getTotalAmount());
            
            // 为订单中的每个商品增加对应商家的余额
            for (OrderItem item : orderItems) {
                log.info("处理订单项: 商品ID={}, 商品名称={}, 数量={}, 单价={}", 
                    item.getProductId(), item.getProductName(), item.getQuantity(), item.getPrice());
                
                // 通过商品表获取商家ID
                Products product = productsDao.queryById(item.getProductId());
                if (product == null) {
                    log.warn("商品信息不存在: 商品ID={}", item.getProductId());
                    // 抛出异常以回滚事务
                    throw new RuntimeException("商品信息不存在: 商品ID=" + item.getProductId());
                }
                
                Long merchantId = product.getMerchantId(); // 从商品信息中获取商家ID
                if (merchantId == null) {
                    log.error("无法获取商家ID: 商品ID={}", item.getProductId());
                    throw new RuntimeException("无法获取商家ID: 商品ID=" + item.getProductId());
                }
                log.info("获取到商家ID: {}", merchantId);
                
                // 获取商家余额
                MerchantBalances merchantBalance = merchantBalancesDao.queryByMerchantId(merchantId);
                if (merchantBalance == null) {
                    // 如果商家余额账户不存在，则创建一个
                    log.info("商家余额账户不存在，创建新账户: 商家ID={}", merchantId);
                    merchantBalance = new MerchantBalances();
                    merchantBalance.setMerchantId(merchantId);
                    merchantBalance.setBalance(0.0);
                    merchantBalance.setUpdatedAt(new Date());
                    int insertResult = merchantBalancesDao.insert(merchantBalance);
                    if (insertResult <= 0) {
                        log.error("创建商家余额账户失败: 商家ID={}", merchantId);
                        // 抛出异常以回滚事务
                        throw new RuntimeException("创建商家余额账户失败: 商家ID=" + merchantId);
                    }
                    log.info("商家余额账户创建成功: 商家ID={}", merchantId);
                }
                
                // 增加商家余额
                double itemTotal = item.getPrice() * item.getQuantity();
                log.info("增加商家余额: 商家ID={}, 增加金额={}", merchantId, itemTotal);
                merchantBalance.setBalance(merchantBalance.getBalance() + itemTotal);
                merchantBalance.setUpdatedAt(new Date());
                int merchantUpdateResult = merchantBalancesDao.update(merchantBalance);
                if (merchantUpdateResult <= 0) {
                    log.error("更新商家余额失败: 商家ID={}", merchantId);
                    // 抛出异常以回滚事务
                    throw new RuntimeException("更新商家余额失败: 商家ID=" + merchantId);
                }
                log.info("商家余额增加成功: 商家ID={}, 增加金额={}", merchantId, itemTotal);
            }
            
            log.info("资金转移成功: 订单ID={}, 用户ID={}, 订单金额={}", order.getOrderId(), order.getUserId(), order.getTotalAmount());
            return Result.ok(true);
        } catch (Exception e) {
            log.error("资金转移时发生异常: 订单ID={}", order.getOrderId(), e);
            return Result.fail("资金转移失败: " + e.getMessage());
        }
    }
    
    /**
     * 回滚Redis中的库存
     * @param orderItems 订单项列表
     */
    private void rollbackStock(List<OrderItem> orderItems) {
        try {
            for (OrderItem item : orderItems) {
                String stockKey = "product:stock:" + item.getProductId();
                RAtomicLong stock = redissonClient.getAtomicLong(stockKey);
                if (stock.isExists()) {
                    stock.addAndGet(item.getQuantity());
                    log.info("回滚商品库存: 商品ID={}, 数量={}", item.getProductId(), item.getQuantity());
                }
            }
        } catch (Exception e) {
            log.error("回滚库存时发生异常", e);
        }
    }
    
    /**
     * 扣减数据库中的库存
     * @param orderId 订单ID
     */
    private void deductDatabaseStock(Long orderId) {
        try {
            List<OrderItem> orderItems = orderItemDao.queryByOrderId(orderId);
            for (OrderItem item : orderItems) {
                Products product = productsDao.queryById(item.getProductId());
                if (product != null) {
                    // 更新数据库中的库存
                    int newStock = product.getStock() - item.getQuantity();
                    if (newStock < 0) {
                        newStock = 0; // 确保库存不会为负数
                    }
                    product.setStock(newStock);
                    productsDao.update(product);
                    
                    // 同步更新Redis中的库存
                    String stockKey = "product:stock:" + item.getProductId();
                    RAtomicLong stock = redissonClient.getAtomicLong(stockKey);
                    stock.set(newStock);
                    
                    log.info("扣减数据库库存成功: 商品ID={}, 原库存={}, 扣减数量={}, 新库存={}", 
                             item.getProductId(), product.getStock() + item.getQuantity(), 
                             item.getQuantity(), newStock);
                }
            }
        } catch (Exception e) {
            log.error("扣减数据库库存时发生异常: 订单ID={}", orderId, e);
        }
    }
    
    /**
     * 生成订单号
     * @return 订单号
     */
    private String generateOrderNo() {
        // 使用Redis生成全局唯一的订单号，避免高并发情况下的重复问题
        String prefix = "ORD" + System.currentTimeMillis();
        String key = "order:no:" + System.currentTimeMillis();
        
        // 使用Redis的原子操作生成序列号
        RAtomicLong sequence = redissonClient.getAtomicLong(key);
        long seq = sequence.incrementAndGet();
        
        // 设置序列号过期时间（24小时），避免一直累积
        if (seq == 1) {
            sequence.expire(24, java.util.concurrent.TimeUnit.HOURS);
        }
        
        // 格式化序列号为6位数字，不足补0
        String sequenceStr = String.format("%06d", seq);
        
        return prefix + sequenceStr;
    }
    
    /**
     * 获取包含订单项的完整订单信息
     * @param orderId 订单ID
     * @return 完整订单信息
     */
    private Order getOrderWithItems(Long orderId) {
        Order order = orderDao.queryById(orderId);
        if (order != null) {
            List<OrderItem> orderItems = orderItemDao.queryByOrderId(orderId);
            // 为每个订单项设置商品图片URL
            for (OrderItem item : orderItems) {
                Products product = productsDao.queryById(item.getProductId());
                if (product != null) {
                    item.setProductImageUrl(product.getImageUrl());
                }
            }
            order.setOrderItems(orderItems);
        }
        return order;
    }
}